package com.example.hotel.common;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.hotel.entity.Login;


import java.util.Calendar;

/**
 * JWT工具类
 */
public class JWTUtil {
    // 用于生成令牌的加密码，当解析令牌时必须提供相同的加密码才能将令牌正确的解析。
    // 也有使用用户密码当做加密码的，但是由于用户的每次请求几乎都要验证令牌，因此需要考虑访问数据库的开销。
    private static final String key = "c475eeaec2d16f750c21e53a61884b35";

    /**
     * 获取token
     *
     * @param worker 登录用户信息
     * @param day 令牌有效期，天
     * @return token
     */
    public static String getToken(Login worker, int day) {
        // 得到令牌有效期终止日期
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE, day);
        // 创建令牌的对象
        JWTCreator.Builder builder = JWT.create();
        // 构建的令牌中包含用户id和用户名的信息
        builder.withClaim("id", worker.getLoginId())
                .withClaim("name", worker.getLoginName())
                .withExpiresAt(instance.getTime());// 添加过期时间
        return builder.sign(Algorithm.HMAC256(key));// 构建令牌秘钥，使用HMAC256算法
    }

    /**
     * 验证token有效性
     *
     * @param token token令牌字符串
     * @return 验证通过返回true, 失败返回false
     */
    public static boolean verify(String token) {
        // 如果令牌为空，直接验证不通过
        if (token == null || token.trim().equals("")) {
            return false;
        } else {
            // 验证令牌能够正常解析
            try {
                JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(key)).build();
                DecodedJWT decodedJWT = jwtVerifier.verify(token);
            } catch (Exception e) {
                return false;
            }
            return true;
        }
    }

    /**
     * 从token令牌字符串中解析出用户的信息
     *
     * @param token 令牌字符串
     * @return 用户信息
     */
    public static Login parseToken(String token) {
        // 验证令牌是否有效
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(key)).build();
        DecodedJWT decodedJWT = jwtVerifier.verify(token);
        // 从解析的令牌中得到id和name
        Claim id = decodedJWT.getClaim("id");
        Claim username = decodedJWT.getClaim("name");
        Login worker = new Login();
        worker.setLoginId(id.asInt());
        worker.setLoginName(username.asString());
        return worker;
    }
}